#pragma once

struct INode;
struct ERenderPhaseMethod;

/*--------------------------------------------------------------------------*/

struct EMigration
{
	enum Mode
	{
	    GoUp = 0,
	    GoDown
	};
};

struct CameraDesc
{
	float						m_farplane;
	float						m_nearplane;
	float						m_fov;
	std::string					m_name;
	ERenderPhaseMethod::Method	m_method;
	GLTexture*					m_output;

	CameraDesc() :
		m_farplane(1000.0f),
		m_nearplane(1.0f),
		m_fov(60.0f),
		m_name("Noname"),
		m_method(ERenderPhaseMethod::DeferredShading),
		m_output(NULL)
	{}
};

/*--------------------------------------------------------------------------*/
class IRenderPhase;

struct SceneCamera
{
	PerspectiveCamera*	m_camera;
	INode*				m_nearestNode;
	INode*				m_newNearestNode;
	std::string			m_name;
	IRenderPhase*		m_renderphase;
	ERenderPhaseMethod::Method	m_method;
	GLTexture*			m_output;

	SceneCamera() :
		m_camera(NULL),
		m_nearestNode(NULL),
		m_newNearestNode(NULL),
		m_renderphase(NULL),
		m_method(ERenderPhaseMethod::DeferredShading)
	{}
};

/*--------------------------------------------------------------------------*/

struct ESceneInstanceFlag
{
	enum Type
	{
	    SceneStarted				= 1 << 0,
	};
};

/*--------------------------------------------------------------------------*/

#define MAX_NODES_PER_SCENE 100000

/*--------------------------------------------------------------------------*/

class SceneInstance:
	public ICriticalSection,
	public ICalc
{
public:
	SceneInstance();
	~SceneInstance();

	enum CriticalSection
	{
	    NodesVector,
	    MarkedForDeleteVector
	};

	/*---ICalc------------------------------------------------------------------*/
	void							OnCalc(uint arg);

	/*--------------------------------------------------------------------------*/
	void							MarkForDelete(INode* node);
	INode*							GetRootNode();

	/*--------------------------------------------------------------------------*/
	PerspectiveCamera*				SetCamera(const CameraDesc& desc);
	PerspectiveCamera*				GetCamera() const;

	IRenderPhase*					GetRenderPhase() const;

	/*--------------------------------------------------------------------------*/
	void							StartScene(const std::string& name, int priority);
	bool							IsStarted();
	/*--------------------------------------------------------------------------*/

	void							RegisterNode(INode* node);
	void							UnregisterNode(INode* node);
	void							ValidateScene();
	void							ValidateNode(INode* node);

	/*--------------------------------------------------------------------------*/

	void							UpdateModelMatrices();

private:
	void							UpdateScene();

	/*--------------------------------------------------------------------------*/
	std::vector<INode*>				m_markedForDelete;
	std::vector<INode*>				m_registeredNodes;
	uint					m_nextFreeNode;
	/*--------------------------------------------------------------------------*/
	SceneCamera						m_sceneCamera;
	uint					m_flags;
	std::string						m_name;

	INode*							m_treeRoot;
	/*--------------------------------------------------------------------------*/
};

